﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using GraphCompiler.Core;
using GraphCompiler.Core.Exceptions;

namespace GraphCompiler.Specification
{
    [TestFixture]
    public class TokenCollectionSpecs
    {
        [Test]
        public void CanBeInitializedWithCollectionInitializer()
        {
            var tokens = new TokenCollection()
            {
                new Token("")
            };

            Assert.AreEqual(1, tokens.Count());
        }

        [Test]
        public void GivenClosingBracketAsFirstToken_ConsidersNextTokenToBeClosingBracket()
        {
            var tokens = new TokenCollection()
            {
                new Token("}")
            };

            Assert.IsTrue(tokens.IsNextTokenClosingBracket);
        }

        [Test]
        public void GivenEmptyCollection_DoesNotConsiderNextTokenToBeClosingBracket()
        {
            var tokens = new TokenCollection();

            Assert.IsFalse(tokens.IsNextTokenClosingBracket);
        }

        [Test]
        public void CanBeInitializedWithParameterListOfStrings()
        {
            var expectedTokens = new TokenCollection();
            expectedTokens.Add(new Token("box"));
            expectedTokens.Add(new Token("{"));
            expectedTokens.Add(new Token("}"));

            var actualTokens = new TokenCollection("box", "{", "}");

            Assert.AreEqual(expectedTokens, actualTokens);
        }

        [Test]
        public void GivenEmptyCollection_IsEqualToSelf()
        {
            var tokens = new TokenCollection();

            Assert.AreEqual(tokens, tokens);
        }

        [Test]
        public void GivenEmptyCollection_IsEqualToOtherEmptyCollection()
        {
            Assert.AreEqual(new TokenCollection(), new TokenCollection());
        }

        [Test]
        public void GivenCollectionWithOneToken_IsNotEqualToEmptyCollection()
        {
            var tokens = new TokenCollection("token");

            Assert.AreNotEqual(tokens, new TokenCollection());
        }

        [Test]
        public void GivenCollectionWithOneToken_IsEqualToSelf()
        {
            var tokens = new TokenCollection("token");

            Assert.AreEqual(tokens, tokens);
        }

        [Test]
        public void GivenCollectionWithOneToken_IsEqualToOtherCollectionWithEqualToken()
        {
            var tokens1 = new TokenCollection();
            tokens1.Add(new Token("token"));

            var tokens2 = new TokenCollection();
            tokens2.Add(new Token("token"));

            Assert.AreEqual(tokens1, tokens2);
        }

        [Test]
        public void GivenCollectionWithOneToken_IsNotEqualToCollectionWithDifferentToken()
        {
            var tokens1 = new TokenCollection();
            tokens1.Add(new Token("token"));

            var tokens2 = new TokenCollection();
            tokens2.Add(new Token("schmoken"));

            Assert.AreNotEqual(tokens1, tokens2);
        }

        [Test]
        public void GivenCollectionWithNoTokens_IsEmpty()
        {
            var tokens = new TokenCollection();

            Assert.IsTrue(tokens.IsEmpty);
        }

        [Test]
        public void GivenCollectionWithOneToken_IsNotEmpty()
        {
            var tokens = new TokenCollection("token");

            Assert.IsFalse(tokens.IsEmpty);
        }

        [ExpectedException(typeof(SyntaxErrorException))]
        [Test]
        public void GivenEmptyCollection_RaisesErrorOnRead()
        {
            var tokens = new TokenCollection();

            tokens.ReadNext();
        }

        [Test]
        public void GivenCollectionWithOneToken_ReadReturnsNextToken()
        {
            var tokens = new TokenCollection("token");

            var expectedToken = new Token("token");

            var actualToken = tokens.ReadNext();

            Assert.AreEqual(expectedToken, actualToken);
        }

        [Test]
        public void GivenCollectionWithTwoTokens_ReadConsumesNextToken()
        {
            var tokens = new TokenCollection("token", "second");

            var expectedTokens = new TokenCollection("second");

            tokens.ReadNext();

            Assert.AreEqual(expectedTokens, tokens);
        }
    }
}
